package com.zwq.poker.dto;

import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.zwq.common.exception.BusinessException;
import com.zwq.poker.CardConstant;
import com.zwq.poker.CardTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;


/**
 * @BelongsProject: cloud-shop
 * @BelongsPackage: com.zwq.poker.dto
 * @Author: zwq
 * @CreateTime: 2025-04-25  19:51
 * @Description: TODO
 * @Version: 1.0
 */
@Data
public class CardDTO implements Serializable {

    private CardDTO(){}
    private static List<Card> cards;
    /**
     * 公共牌
     */
    private List<Card> commonCard;

    /**
     * 出牌
     */
    private Stack<DiscardRecord> cardStack;

    public static CardDTO of(){
        return new CardDTO();
    }

    public void init() {
        cards = new ArrayList<Card>(54);
        for (CardTypeEnum cardType : CardTypeEnum.values()) {
            for (String cardNo : CardConstant.CARDS) {
                cards.add(new Card(cardType, cardNo));
            }
        }
        cards.add(new Card(null, CardConstant.JOKER_A));
        cards.add(new Card(null, CardConstant.JOKER_B));
    }

    public void shuffle(){
        shuffle(0);
    }

    /**
     * 发牌斗地主
     * @return
     */
    public List<List<Card>> dealCard(){
        List<Card> cards = new ArrayList<>(getCards());
        commonCard = new ArrayList<>();
        for(int i = 0;i<3;i++){
            Card card = cards.remove(ThreadLocalRandom.current().nextInt(cards.size()));
            commonCard.add(card);
        }

        List<List<Card>> cardGroup = new ArrayList<>();
        for (int i = 0; i <3; i++) {
            cardGroup.add(new ArrayList<Card>());
        }

        int pointer =0;
        for (int i = 0; i < cards.size(); i++) {
            for (List<Card> cardList : cardGroup) {
                if (pointer == cards.size()) {
                    break;
                }
                cardList.add(cards.get(pointer));
                pointer++;
            }
        }

        while(pointer<cards.size()){
            for (List<Card> cardList : cardGroup) {
                cardList.add(cards.get(pointer));
                pointer++;
            }

        }

        return cardGroup;
    }


    /**
     * 洗牌
     * @param minShuffleNum 最小洗牌次数
     */
    public void shuffle(int minShuffleNum){
        Random random = new Random();
        Card[] cardArray = cards.toArray(new Card[cards.size()]);
        //洗牌次数
        int shuffleNumber = ThreadLocalRandom.current().nextInt(minShuffleNum, cards.size());
        for (int i = 0; i < shuffleNumber; i++) {
            for (int j = 0; j < cardArray.length; j++) {
                int randomInt = random.nextInt(cards.size());
                Card currcntCard = cardArray[j];
                cardArray[j] = cardArray[randomInt];
                cardArray[randomInt] = currcntCard;
            }
        }
        cards = Arrays.asList(cardArray);
    }

    /**
     * 出牌
     * @param outCards
     */
    public void Discard(String userId,List<Card> outCards){
        if (Objects.isNull(cardStack)) {
            cardStack = new Stack<>();
        }

        DiscardRecord LastCardRecord = cardStack.peek();
        if (Objects.nonNull(LastCardRecord)) {
            List<Card> card = LastCardRecord.getCard();
            //1.判断是不是王炸
            //2.判断是不是炸弹
            //3.判断出牌数量
            //4.判断出牌类型
            //5.判断出牌大小
            //6.判断出牌是否连续
            //7.判断出牌是否是顺子
            //8.判断出牌是否是连对
            //9.判断出牌是否是飞机
            //10.判断出牌是否是三带一
            //11.判断出牌是否是三带1对
            //12.判断出牌是否是四带二
            //13.判断出牌是否是四带二对
            //13.判断出牌是否是飞机带一
            //14.判断出牌是否是飞机带二对

            if (card.size() != outCards.size()) {
                throw new BusinessException("出牌数量不匹配");
            }
        }
        cardStack.push(new DiscardRecord(userId,outCards));
    }


    /**
     * 比牌
     * @param card1
     * @param card2
     * @return
     */
    public boolean equalCard(Card card1,Card card2){
        return card1.getCardType() == card2.getCardType() && card1.getNo().equals(card2.getNo());
    }

    public List<Card> getCards(){
        return cards;
    }

    /**
     * 获取公共牌
     * @return
     */
    public List<Card> getCommonCard(){
        return commonCard;
    }

    @Data
    @AllArgsConstructor
    @Schema(name = "卡片实体类")
    public static class Card {
        @Schema(name = "卡片类型")
        private CardTypeEnum cardType;

        @Schema(name = "卡片编号")
        private String no;
    }


    @Data
    @AllArgsConstructor
    @Schema(name = "出牌记录")
    public static class DiscardRecord {
        @Schema(name = "用户id")
        private String userId;

        @Schema(name = "卡片")
        private List<Card> card;
    }


}


